/*
 * Copyright (C) 2010,2011  Paulo Cesar Pereira de Andrade.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Authors:
 *	Paulo Cesar Pereira de Andrade
 */

#include "exl.h"

#define r0			thread_self->r0
#define ss			thread_self->ess
#define bp			thread_self->ebp
#define sp			thread_self->esp
#define obj			thread_self->obj
#define ret			thread_self->ret
#define flt			thread_self->flt

/*
 * Implementation
 */
void
evm_a_ne(evalue_t *v)
{
    eint_t	value;
    if (v->v.o == r0.v.o)
	value = 0;
    else if (evector_type_p(r0.t) &&
	     (r0.t & ~t_const) == t_string &&
	     (v->t & ~t_const) == (r0.t & ~t_const) &&
	     v->v.V->length == r0.v.V->length)
	value = memcmp(v->v.V->v.u8, r0.v.V->v.u8, r0.v.V->length) != 0;
    else
	value = 1;
    r0.t = t_int;
    r0.v.i = value;
}

void
evm_a_eq(evalue_t *v)
{
    eint_t	value;
    if (v->v.o == r0.v.o)
	value = 1;
    else if (evector_type_p(r0.t) &&
	     (r0.t & ~t_const) == t_string &&
	     (v->t & ~t_const) == (r0.t & ~t_const) &&
	     v->v.V->length == r0.v.V->length)
	value = memcmp(v->v.V->v.u8, r0.v.V->v.u8, r0.v.V->length) == 0;
    else
	value = 0;
    r0.t = t_int;
    r0.v.i = value;
}

void
evm_a_and(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_and(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_and(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_and(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_an_integer);
	    evector_and(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_or(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    /* FIXME noop */
	    evector_int_or(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_or(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_or(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_an_integer);
	    evector_or(v->v.o, r0.v.o,
		       v->t & ~(t_const|t_vector),
		       r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_xor(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    /* FIXME noop */
	    evector_int_xor(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_xor(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_xor(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_an_integer);
	    evector_xor(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_mul2(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_mul2(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_mul2(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_mul2(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_mul2(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_mul2(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_mul2(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_mul2(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_mul2(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_mul2(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_real_number);
	    evector_mul2(v->v.o, r0.v.o,
			 v->t & ~(t_const|t_vector),
			 r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_div2(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_div2(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_div2(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_div2(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_div2(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_div2(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_div2(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_div2(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_div2(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_div2(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_real_number);
	    evector_div2(v->v.o, r0.v.o,
			 v->t & ~(t_const|t_vector),
			 r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_shl(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_shl(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_shl(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_shl(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_shl(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_shl(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_shl(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_real_number);
	    evector_shl(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_shr(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_shr(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_shr(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_shr(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_shr(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_shr(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_shr(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_real_number);
	    evector_shr(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_add(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_add(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_add(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_add(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_add(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_add(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_add(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_add(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_add(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_add(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_number);
	    evector_add(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_sub(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_sub(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_sub(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_sub(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_sub(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_sub(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_sub(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_sub(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_sub(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_sub(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_number);
	    evector_sub(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_mul(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_mul(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_mul(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_mul(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_mul(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_mul(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_mul(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_mul(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_mul(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_mul(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_number);
	    evector_mul(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_div(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_div(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_div(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_div(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:	case t_shz:
	    evector_mpz_div(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:	case t_shq:
	    evector_mpq_div(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:	case t_shr:
	    evector_mpr_div(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_div(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:	case t_sqq:
	    evector_cqq_div(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:	case t_shc:
	    evector_mpc_div(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_number);
	    evector_div(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_trunc2(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_trunc(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_trunc(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_trunc(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_trunc(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_trunc(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_trunc(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_real_number);
	    evector_trunc(v->v.o, r0.v.o,
			  v->t & ~(t_const|t_vector),
			  r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_rem(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_rem(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_rem(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_rem(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:	case t_shz:
	    evector_mpz_rem(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:	case t_shq:
	    evector_mpq_rem(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:	case t_shr:
	    evector_mpr_rem(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_real_number);
	    evector_rem(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_atan2(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_atan2(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_atan2(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_atan2(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_atan2(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_atan2(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_atan2(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_atan2(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_atan2(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_atan2(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_number);
	    evector_atan2(v->v.o, r0.v.o,
			  v->t & ~(t_const|t_vector),
			  r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_pow(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_pow(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_pow(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_pow(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_pow(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_pow(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_pow(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_pow(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_pow(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_pow(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_number);
	    evector_pow(v->v.o, r0.v.o,
			v->t & ~(t_const|t_vector),
			r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}

void
evm_a_hypot(evalue_t *v)
{
    switch (v->t) {
	case t_void:
	    evector_int_hypot(0, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_int:
	    evector_int_hypot(v->v.i, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_float:
	    evector_float_hypot(v->v.d, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpz:		case t_shz:
	    evector_mpz_hypot(v->v.mpz, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpq:		case t_shq:
	    evector_mpq_hypot(v->v.mpq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpr:		case t_shr:
	    evector_mpr_hypot(v->v.mpr, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cdd:
	    evector_cdd_hypot(v->v.cdd, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_cqq:		case t_sqq:
	    evector_cqq_hypot(v->v.cqq, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	case t_mpc:		case t_shc:
	    evector_mpc_hypot(v->v.mpc, r0.v.o, r0.t & ~(t_const|t_vector));
	    break;
	default:
	    if (!evector_type_p(v->t))
		evm_raise(except_not_a_number);
	    evector_hypot(v->v.o, r0.v.o,
			  v->t & ~(t_const|t_vector),
			  r0.t & ~(t_const|t_vector));
	    break;
    }
    r0.v.o = obj;
    r0.t = eobject_type(obj);
}
